package com.tanhan.mindapp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhan.mindapp.dao.SysMenu;
import com.tanhan.mindapp.dao.SysRole;
import com.tanhan.mindapp.dao.SysUser;
import com.tanhan.mindapp.dao.SysUserDTO.SysUserCreateDTO;
import com.tanhan.mindapp.dao.SysUserDTO.SysUserQueryDTO;
import com.tanhan.mindapp.mapper.SysUserMapper;
import com.tanhan.mindapp.service.*;
import com.tanhan.mindapp.utils.PageUtils;
import com.tanhan.mindapp.utils.TokenUtils;
import com.tanhan.mindapp.exception.AppException;
import com.tanhan.mindapp.exception.AppExceptionCodeMsg;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private TokenUtils tokenUtils;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    @Autowired
    @Lazy
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    @Lazy
    private SysMenuService sysMenuService;

    // 登录
    @Override
    public String login(String userName, String password) {
        SysUser user = findByUsername(userName);

        // 用户不存在或密码错误
        if (user == null || !passwordEncoder.matches(password, user.getPassword())) {
            throw new AppException(AppExceptionCodeMsg.NOT_FOUND_USER);
        }
        // 生成token
        Map<String, Object> map = new HashMap<>();
        map.put("user_name", userName);
        map.put("id", user.getId());
        // 添加用户权限信息到token中
        List<String> permissions = this.getUserPermissions(user.getId());
        map.put("authorities", permissions);
        return tokenUtils.getJwt(map);
    }

    // 添加用户
    @Override
    public boolean addUser(SysUserCreateDTO sysUserCreateDTO) {
        // 检查用户名是否已存在
        SysUser existingUser = findByUsername(sysUserCreateDTO.getUserName());
        if (existingUser != null) {
            throw new AppException(AppExceptionCodeMsg.USER_ALREADY_EXISTS);
        }
        // 创建新用户
        SysUser sysUser = new SysUser();
        // 密码加密后存储
        sysUser.setPassword(passwordEncoder.encode(sysUserCreateDTO.getPassword()));
        sysUser.setUserName(sysUserCreateDTO.getUserName());
        sysUser.setNickName(sysUserCreateDTO.getNickName());
        sysUser.setEmail(sysUserCreateDTO.getEmail());
        sysUser.setPhone(sysUserCreateDTO.getPhone());
        // 保存用户到数据库
        return this.save(sysUser);
    }

    // 根据用户名查询用户
    @Override
    public SysUser findByUsername(String userName) {
        Map<String, Object> map = new HashMap<>();
        map.put("user_name", userName);
        List<SysUser> users = this.baseMapper.selectByMap(map);
        return users.isEmpty() ? null : users.get(0);
    }

    // 分页条件查询
    @Override
    public IPage<SysUser> selectUserPage(SysUserQueryDTO sysUserQueryDTO) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();

        // 添加自定义条件查询
        if (sysUserQueryDTO.getNickName() != null && !sysUserQueryDTO.getNickName().isEmpty()) {
            queryWrapper.like("nick_name", sysUserQueryDTO.getNickName());
        }
        if (sysUserQueryDTO.getPhone() != null && !sysUserQueryDTO.getPhone().isEmpty()) {
            queryWrapper.like("phone", sysUserQueryDTO.getPhone());
        }
        if (sysUserQueryDTO.getStatus() != null && !sysUserQueryDTO.getStatus().isEmpty()) {
            queryWrapper.eq("status", sysUserQueryDTO.getStatus());
        }
        // 使用 PageUtils 进行分页（需要修改 PageUtils 添加相应重载方法）
        IPage<SysUser> sysUserIPage = PageUtils.pageQuery(this, sysUserQueryDTO, queryWrapper);
        sysUserIPage.getRecords().forEach(user -> {
            // 获取用户角色
            List<SysRole> roles = sysUserRoleService.getRolesByUserId(user.getId());
            user.setRoles(roles);
        });
        return sysUserIPage;
    }

    // 通过ID查询用户，携带角色信息
    @Override
    public SysUser getUserWithRoles(String id) {
        // 查询用户基本信息
        SysUser user = this.getById(id);
        if (user != null) {
            // 获取用户角色列表
            List<SysRole> roles = sysUserRoleService.getRolesByUserId(id);
            // 设置角色列表到用户对象中
            user.setRoles(roles);
        }
        return user;
    }

    @Override
    public List<SysMenu> getUserMenusByToken(String token) {
        // 解析token获取用户信息
        Map<String, Object> claims = tokenUtils.parseJwt(token);
        String userId = (String) claims.get("id");

        // 查询用户角色列表
        List<SysRole> roles = sysUserRoleService.getRolesByUserId(userId);

        // 收集角色对应的菜单ID
        Set<String> menuIdSet = new HashSet<>();
        for (SysRole role : roles) {
            List<String> menuIds = sysRoleMenuService.getMenuIdsByRoleId(String.valueOf(role.getId()));
            menuIdSet.addAll(menuIds);
        }

        // 根据菜单ID查询完整菜单列表
        if (menuIdSet.isEmpty()) {
            return new ArrayList<>();
        }

        QueryWrapper<SysMenu> menuQueryWrapper = new QueryWrapper<>();
        menuQueryWrapper.in("id", menuIdSet);
        menuQueryWrapper.orderByAsc("order_num"); // 按排序字段升序排列

        return sysMenuService.list(menuQueryWrapper);
    }


    /**
     * 通过用户id获取用户权限
     */
    private List<String> getUserPermissions(String userId) {
        // 查询用户角色列表
        List<SysRole> roles = sysUserRoleService.getRolesByUserId(userId);
        System.out.println("1223Login" + roles);
        // 使用Set去重，存储角色对应的菜单ID
        Set<String> menuIdSet = new HashSet<>();
        // 查询每个角色对应的菜单权限
        for (SysRole role : roles) {
            List<String> menuIds = sysRoleMenuService.getMenuIdsByRoleId(String.valueOf(role.getId()));
            menuIdSet.addAll(menuIds);
        }
        return menuIdSet.stream()
                .map(menuId -> sysMenuService.getById(menuId))
                .filter(Objects::nonNull)
                .map(SysMenu::getPerms)
                .collect(Collectors.toList());
    }
}
